using System;
using Slaks.Graphs.GraphBuilder;
namespace Slaks.Graphs.Algorithms.ExperimentalDistances
{
	public class MCSmixed : GraphDistanceBase
	{
        public MCSmixed()
            : base()
        {
        }

        public MCSmixed(Graph one, Graph two) 
            : base ( one, two )
        {
        }	
				public override bool CanOperateOnRepresentation (GraphBuilder.BuilderType builderType)
		{
			switch(builderType)
			{
			case BuilderType.StandardRepresentationSchenker:
			case BuilderType.ExtractorBuilderNodesOnly:
			case BuilderType.StandardRepresentationSlaks:
				return true;
			}
			return false;
		}
		/// <summary>
		/// MCSsubgraph and MCSlimited
		/// </summary>
		/// <param name="one"></param>
		/// <param name="two"></param>
		/// <returns></returns>
		public override double GetDistance ()
		{
			double result;
			Graph maxCommonSubgraph = (one.GetMCS(two));
			double mcsVertexCount = maxCommonSubgraph.GetVertexCount();
			double mcsEdgeCount = maxCommonSubgraph.GetEdgeCount();
			double mcsCommonGraphSize = mcsEdgeCount + mcsVertexCount;

			double graphSizeOneVertexCount = one.GetVertexCount();
			double graphSizeTwoVertexCount = two.GetVertexCount();

			double graphSizeOne = one.GetGraphSizeVertexEdgeCount;
			double graphSizeTwo = two.GetGraphSizeVertexEdgeCount;

			double graphSizeOneEdgeCount = one.GetEdgeCount();
			double graphSizeTwoEdgeCount = two.GetEdgeCount();

			//if (mcsVertexCount == graphSizeOneVertexCount)
			//	return graphSizeOneVertexCount / graphSizeTwoVertexCount;
			//if (mcsVertexCount == graphSizeTwoVertexCount)  
			//	return graphSizeTwoVertexCount / graphSizeOneVertexCount;
			if (mcsVertexCount*2 > graphSizeOneVertexCount && graphSizeOneVertexCount < graphSizeTwoVertexCount)
			{
				return 1 - graphSizeOne/Math.Max(graphSizeOne, graphSizeTwo);
			}
			else if (mcsVertexCount*2 > graphSizeTwoVertexCount && graphSizeOneVertexCount > graphSizeTwoVertexCount)
			{
				return 1 - graphSizeTwo/Math.Max(graphSizeOne, graphSizeTwo);
			}
			double limitedSizeOne =
				(graphSizeOneEdgeCount > graphSizeOneVertexCount) ? graphSizeOneVertexCount*2 : graphSizeOneVertexCount + graphSizeOneEdgeCount;
			double limitedSizeTwo =
				(graphSizeTwoEdgeCount > graphSizeTwoVertexCount) ? graphSizeTwoVertexCount*2 : graphSizeTwoVertexCount + graphSizeTwoEdgeCount;

			if (limitedSizeOne > limitedSizeTwo)
			{
				result = 1 - mcsCommonGraphSize/limitedSizeOne;
			}
			else
			{
				result = 1 - mcsCommonGraphSize/limitedSizeTwo;
			}

			if (result < 0) result = 0;
			return result;
		}
	}
}